/**
 * AdvancedTreeModel.java
 *
 * Este código foi baseado no exemplo do site do ZK: http://www.zkoss.org/zkdemo/tree/dynamic_tree
 * 
 * Projeto: SGA-LEDS
 *
 * Rodrigo Soares Maia IFES - Instituto Federal do Espírito Santo - Campus Serra
 */
package controleAtividades.cih;

import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.DefaultTreeNode;

public class AdvancedTreeModel<T> extends DefaultTreeModel<T>
{
    public DefaultTreeNode<T> _root; //GAMBI estah como public para poder acessar dos dois pacotes

    public AdvancedTreeModel(TreeNode treeNode)
    {
        super(treeNode);
        _root = treeNode;
    }

    /**
     * remove the nodes which parent is
     * <code>parent</code> with indexes
     * <code>indexes</code>
     *
     * @param parent The parent of nodes are removed
     * @param indexFrom the lower index of the change range
     * @param indexTo the upper index of the change range
     * @throws IndexOutOfBoundsException - indexFrom < 0 or indexTo > number of
     * parent's children
     */
    public void remove(DefaultTreeNode<T> parent, int indexFrom, int indexTo) throws IndexOutOfBoundsException
    {
        DefaultTreeNode<T> stn = parent;
        for (int i = indexTo; i >= indexFrom; i--)
        {
            try
            {
                stn.getChildren().remove(i);
            }
            catch (Exception exp)
            {
                exp.printStackTrace();
            }
        }
    }

    public void remove(DefaultTreeNode<T> target) throws IndexOutOfBoundsException
    {
        int index = 0;
        DefaultTreeNode<T> parent = null;
        // find the parent and index of target
        parent = dfSearchParent(_root, target);
        for (index = 0; index < parent.getChildCount(); index++)
        {
            if (parent.getChildAt(index).equals(target))
            {
                break;
            }
        }
        remove(parent, index, index);
    }

    /**
     * insert new nodes which parent is
     * <code>parent</code> with indexes
     * <code>indexes</code> by new nodes
     * <code>newNodes</code>
     *
     * @param parent The parent of nodes are inserted
     * @param indexFrom the lower index of the change range
     * @param indexTo the upper index of the change range
     * @param newNodes New nodes which are inserted
     * @throws IndexOutOfBoundsException - indexFrom < 0 or indexTo > number of
     * parent's children
     */
    public void insert(DefaultTreeNode<T> parent, int indexFrom, int indexTo, DefaultTreeNode<T>[] newNodes)
            throws IndexOutOfBoundsException
    {
        DefaultTreeNode<T> stn = parent;
        for (int i = indexFrom; i <= indexTo; i++)
        {
            try
            {
                stn.getChildren().add(i, newNodes[i - indexFrom]);
            }
            catch (Exception exp)
            {
                throw new IndexOutOfBoundsException("Out of bound: " + i + " while size=" + stn.getChildren().size());
            }
        }
    }

    /**
     * append new nodes which parent is
     * <code>parent</code> by new nodes
     * <code>newNodes</code>
     *
     * @param parent The parent of nodes are appended
     * @param newNodes New nodes which are appended
     */
    public void add(DefaultTreeNode<T> parent, DefaultTreeNode<T>[] newNodes)
    {
        DefaultTreeNode<T> stn = (DefaultTreeNode<T>) parent;

        //se o no jah tiver filhas, os novos sao adicionados...
        if (stn.getChildren() != null)
        {
            for (int i = 0; i < newNodes.length; i++)
            {
                    stn.getChildren().add(newNodes[i]);
            }
        }
        else
        {
            //TODO nao tem como adicionar o cara num noh folha :/
            //stn.add(newNodes[i]);
        }

    }

    private DefaultTreeNode<T> dfSearchParent(DefaultTreeNode<T> node, DefaultTreeNode<T> target)
    {
        if (node.getChildren() != null && node.getChildren().contains(target))
        {
            return node;
        }
        else
        {
            int size = getChildCount(node);
            for (int i = 0; i < size; i++)
            {
                DefaultTreeNode<T> parent = dfSearchParent((DefaultTreeNode<T>) getChild(node, i), target);
                if (parent != null)
                {
                    return parent;
                }
            }
        }
        return null;
    }
}
